#!/usr/bin/python

import sys
import dbus
import flimflam

bus = dbus.SystemBus()

manager = dbus.Interface(bus.get_object("org.chromium.flimflam", "/"),
                                        "org.chromium.flimflam.Manager")

if len(sys.argv) < 2:
    print "Usage: %s <command>" % (sys.argv[0])
    print ""
    print "  state"
    print "  recheck-portal"
    print "  services"
    print "  passphrase <service> [passphrase]"
    print "  autoconnect <service> [autoconnect]"
    print "  connect <service>"
    print "  disconnect <service>"
    print "  remove <service>"
    print ""
    print "  scan [type]"
    print "  enable <type>"
    print "  disable <type>"
    print "  offlinemode [on|off]"
    print ""
    print "  dev <interface>"
    print "  dev <interface> scan"
    print "  dev <interface> networks"
    print "  dev <interface> connect <network>"
    print "  dev <interface> disconnect [network]"
    print "  dev <interface> powered [on|off]"
    sys.exit(1)

def print_properties(object_path, properties):
    print "[ %s ]" % (object_path)
    for key in properties.keys():
        if key == "Networks":
            continue

        if key in ["Powered", "Scanning", "Connected",
                   "Available", "Remember", "Default"]:
            if properties[key] == dbus.Boolean(1):
                val = "true"
            else:
                val = "false"
        elif key in ["Strength", "Priority"]:
            val = int(properties[key])
        else:
            val = str(properties[key])

        print "     %s = %s" % (key, val)

def print_networks(networks):
    for object_path in networks:
        network = dbus.Interface(
            bus.get_object("org.chromium.flimflam", object_path),
            "org.chromium.flimflam.Network")

        properties = network.GetProperties(utf8_strings = True)

        if properties["Connected"] == dbus.Boolean(1):
            connected = "*"
        else:
            connected = " "

        if "Name" in properties.keys():
            name = properties["Name"]
        else:
            name = ""

        strength = int(properties["Strength"])

        details = ""
        try:
            details += "{" + properties["WiFi.Mode"] + "} "
        except Exception, _:
            pass
        try:
            details += "{" + properties["WiFi.Security"] + "} "
        except Exception, _:
            pass
        if "WiFi.Passphrase" in properties.keys():
            if properties["WiFi.Passphrase"] != "":
                details += "{passphrase present}"

        print "%s %-26s %3d%%  %s" % (connected, name, strength, details)

def select_network(networks, name):
    for object_path in networks:
        network = dbus.Interface(
            bus.get_object("org.chromium.flimflam", object_path),
            "org.chromium.flimflam.Network")

        properties = network.GetProperties(utf8_strings = True)

        if properties["Name"] != name:
            continue

        if properties["Connected"] == dbus.Boolean(1):
            print "Already connected to network %s" % (name)
            break

        print "Selecting network %s" % (name)

        network.Connect()

def disconnect_network(networks, name):
    for object_path in networks:
        network = dbus.Interface(
            bus.get_object("org.chromium.flimflam", object_path),
            "org.chromium.flimflam.Network")

        properties = network.GetProperties(utf8_strings = True)

        if name != "" and properties["Name"] != name:
            continue

        if properties["Connected"] == dbus.Boolean(1):
            name = properties["Name"]
            print "Disconnecting from network %s" % (name)
            network.Disconnect()

def print_services(services):
    for object_path in services:
        service = dbus.Interface(
            bus.get_object("org.chromium.flimflam", object_path),
            "org.chromium.flimflam.Service")

        properties = service.GetProperties(utf8_strings = True)

        identifier = object_path[object_path.rfind("/") + 1:]

        if properties["Favorite"] == dbus.Boolean(1):
            favorite = "*"
        else:
            favorite = " "

        if "Name" in properties.keys():
            name = properties["Name"]
        else:
            name = "{" + properties["Type"] + "}"

        print "%s %-26s { %s }" % (favorite, name, identifier)

def main():
    if sys.argv[1] == "state":
        properties = manager.GetProperties(utf8_strings = True)

        print "System is %s" % (properties["State"])

    elif sys.argv[1] == "recheck-portal":
        manager.RecheckPortal()
        print "Rechecking portal state"

    elif sys.argv[1] in ["services", "list", "show"]:
        properties = manager.GetProperties(utf8_strings = True)

        print_services(properties["Services"])

    elif sys.argv[1] in ["passphrase", "pass"]:
        if (len(sys.argv) < 3):
            print "Need at least service parameter"
            sys.exit(1)

        path = "/profile/default/" + sys.argv[2]

        service = dbus.Interface(bus.get_object("org.chromium.flimflam", path),
                                 "org.chromium.flimflam.Service")

        if (len(sys.argv) > 3):
            passphrase = sys.argv[3]

            service.SetProperty("Passphrase", passphrase)

            print "Passphrase %s set for %s" % (passphrase, sys.argv[2])
        else:
            properties = service.GetProperties(utf8_strings = True)

            if "Name" in properties.keys():
                name = properties["Name"]
            else: name = "{" + properties["Type"] + "}"

            if "Passphrase" in properties.keys():
                passphrase = properties["Passphrase"]
            else:
                passphrase = "not set"

            print "Passphrase for %s is %s" % (name, passphrase)

    elif sys.argv[1] in ["autoconnect", "autoconn"]:
        if (len(sys.argv) < 3):
            print "Need at least service parameter"
            sys.exit(1)

        path = "/profile/default/" + sys.argv[2]

        service = dbus.Interface(bus.get_object("org.chromium.flimflam", path),
                                 "org.chromium.flimflam.Service")

        if (len(sys.argv) > 3):
            autoconnect = flimflam.make_dbus_boolean(sys.argv[3])

            service.SetProperty("AutoConnect", autoconnect)

            print "Auto connect %s for %s" % (autoconnect, sys.argv[2])
        else:
            properties = service.GetProperties(utf8_strings = True)

            if "Name" in properties.keys():
                name = properties["Name"]
            else:
                name = "{" + properties["Type"] + "}"

            if "AutoConnect" in properties.keys():
                autoconnect = properties["AutoConnect"]
            else:
                autoconnect = dbus.Boolean(0)

            print "Auto connect %s for %s" % (autoconnect, name)

    elif sys.argv[1] in ["connect", "conn"]:
        if (len(sys.argv) < 3):
            print "Need at least service parameter"
            sys.exit(1)

        path = "/profile/default/" + sys.argv[2]

        service = dbus.Interface(bus.get_object("org.chromium.flimflam", path),
                                 "org.chromium.flimflam.Service")

        try:
            service.Connect(timeout=60000)
        except dbus.DBusException, error:
            print "%s: %s" % (error.get_dbus_name(), error.message)

    elif sys.argv[1] in ["disconnect", "disc"]:
        if (len(sys.argv) < 3):
            print "Need at least service parameter"
            sys.exit(1)

        path = "/profile/default/" + sys.argv[2]

        service = dbus.Interface(bus.get_object("org.chromium.flimflam", path),
                                 "org.chromium.flimflam.Service")

        try:
            service.Disconnect()
        except dbus.DBusException, error:
            print "%s: %s" % (error.get_dbus_name(), error.message)

    elif sys.argv[1] in ["remove"]:
        if (len(sys.argv) < 3):
            print "Need at least service parameter"
            sys.exit(1)

        path = "/profile/default/" + sys.argv[2]

        service = dbus.Interface(bus.get_object("org.chromium.flimflam", path),
                                 "org.chromium.flimflam.Service")

        properties = service.GetProperties(utf8_strings = True)

        if properties["Favorite"] == dbus.Boolean(0):
            print "Only favorite services can be removed"
            sys.exit(1)

        try:
            service.Remove()
        except dbus.DBusException, error:
            print "%s: %s" % (error.get_dbus_name(), error.message)

    elif sys.argv[1] == "scan":
        if len(sys.argv) > 2:
            manager.RequestScan(sys.argv[2])
        else:
            manager.RequestScan("")

    elif sys.argv[1] == "enable":
        if len(sys.argv) > 2:
            manager.EnableTechnology(sys.argv[2])
        else:
            manager.EnableTechnology("")

    elif sys.argv[1] == "disable":
        if len(sys.argv) > 2:
            manager.DisableTechnology(sys.argv[2])
        else:
            manager.DisableTechnology("")

    elif sys.argv[1] in ["offlinemode", "flightmode"]:
        if len(sys.argv) > 2:
            active = flimflam.make_dbus_boolean(sys.argv[2])
            manager.SetProperty("OfflineMode", active)
        else:
            properties = manager.GetProperties(utf8_strings = True)
            print "Offline mode is %s" % (properties["OfflineMode"])

    elif sys.argv[1] == "dev":
        properties = manager.GetProperties(utf8_strings = True)

        interface = ""
        command = ""
        value = ""

        if len(sys.argv) > 2:
            interface = sys.argv[2]
            if len(sys.argv) > 3:
                command = sys.argv[3]
                if len(sys.argv) > 4:
                    value = sys.argv[4]

        for path in properties["Devices"]:
            device = dbus.Interface(
                bus.get_object("org.chromium.flimflam", path),
                "org.chromium.flimflam.Device")

            properties = device.GetProperties(utf8_strings = True)

            if (interface != "" and
                properties.get("Interface", "") != interface and
                path != interface):
                continue

            if command == "scan":
                if properties["Type"] in ["wifi", "wimax"]:
                    interface = properties["Interface"]
                    print "Scan for device %s" % (interface)
                    device.ProposeScan()
                else:
                    print "No scanning for device %s" % (interface)
            elif command in ["networks", "net"]:
                if "Networks" in properties.keys():
                    print_networks(properties["Networks"])
                else:
                    print "Device has no networks"
            elif command in ["connect", "conn"] and value != "":
                if "Networks" in properties.keys():
                    select_network(properties["Networks"], value)
                else:
                    print "Device can't connect networks"
            elif command in ["connect", "conn"]:
                print "Need to specify network"
            elif command in ["disconnect", "disc"] and value != "":
                if "Networks" in properties.keys():
                    disconnect_network(properties["Networks"], value)
                else:
                    print "Device has no networks"
            elif command in ["discconnect", "disc"]:
                if "Networks" in properties.keys():
                    disconnect_network(properties["Networks"], "")
                else:
                    print "Device has no networks"
            elif command == "powered" and value != "":
                powered = flimflam.make_dbus_boolean(value)
                device.SetProperty("Powered", powered)
            elif command == "powered":
                interface = properties.get("Interface", "unknown")
                if properties["Powered"] == dbus.Boolean(1):
                    powered = "on"
                else:
                    powered = "off"
                print "Device %s is powered %s" % (interface, powered)
            elif command == "list" or command == "":
                print_properties(path, properties)
            else:
                print "Unknown command"

    else:
        print "Unknown command"

if __name__ == "__main__":
    main()
